TITL DAI FIRMWARE 1E5F8-1E7D1 V1.1 ORG :E5F8 * * * ************ * FPT SQRT * ************ * * MACC = SQRT (MACC). * * Method: approximation followed by Newton * iterations. * * Let X= 2^(2K)*F. Then 2^(2K) is exponent and F * is mantissa. * * Then SQRT(X)=2^K*SQRT(F). 2^K is exp/2. * SQRT(F)=P(i): * 1st approx: P(1)=a*F+b. * 0.5<=F<1: values a1 and b1. * 1<=F<2: values a2 and b2. * Iterations: P(i+1)=(P(i)+F/P(i))/2. * Final SQRT(F): P(3). * * Exit: All registers preserved. * XSQRT PUSH PSW PUSH B PUSH D PUSH H CALL :EBF1 Exp.byte MACC in A (2K) JZ :E63A Abort if MACC=0 RLC JC :E9D0 Run argument error if nr REM in MACC is negative RLC RRC RAR ORA A RAR A is exp/2 (K) PUSH PSW Save it MVI A,:00 Set A=0 if lsb exp =0 LXI D,:E65F Addr a1,b1 for 0.5<=F<1 JNC :E618 INR A Set A=1 if lsb exp =1 LXI D,:E657 Addr a2,b2 for 1<=F<2 L1E117 MOV M,A Init exp byte MACC PUSH H Save addr MACC LXI H,:00E3 CALL :E11C Copy MACC (F) into 00E3-E6 XCHG PUSH H Save addr a/b CALL :EA59 Calc a*F POP H INX H INX H INX H INX H Pnts to b CALL :EA72 Calc P(1)=a*F+b CALL :E63D Calc P(2) CALL :E63D Calc P(3); result in MACC REM and reg ABCD POP H Get addr MACC POP B Get exp/2 (K) in B ADD B Add it to exp SQRT(F) ANI :7F Result must be positive MOV M,A Final exp.byte into MACC NOP L1E118 JMP :C14D Popall, ret REM * Calculate P(i+1): REM L1E119 LXI H,:00E7 PUSH H CALL :E9DB Copy P(i) into 00E7-EA LXI H,:00E3 CALL :E9FB Copy F from 00E3-E6 into REM MACC POP H PUSH H CALL :EA20 Calc F/P(i) POP H CALL :EA72 Calc P(i)+F/P(i) DCR A exp minus 1: divide by 2 ANI :7F Skip sign bit RET REM * CONSTANTS FOR 'XSQRT': REM L1E275 DATA :7F a1: 0.578125 DATA :D2 DATA :D0 DATA :1C * DATA :00 b1: 0.421875 DATA :99 DATA :EE DATA :14 * L1E277 DATA :00 a2: 0.411744 DATA :94 DATA :00 DATA :00 * DATA :7F b2: 0.601289 DATA :D8 DATA :00 DATA :00 * *********** * FPT EXP * *********** * * MACC = E ^ MACC. * * Method: Polynomial approximation. * * Let E^X = 2^n * 2^d * 2^z: * Then X/ln2 = n + d + z. * n: integral portion of the real number. * d: a discrete fraction (1/8, 3/8, 5/8 * or 7/8) of the fractional part. * z: remainder: -1/8 <= z <= 1/8. * Approximation for 2^z: * 2^z = a0 + a1*z + a2*z^2 + .... + a5*z^5. * XEXP PUSH PSW PUSH B PUSH D PUSH H LDA :00D5 Get exp.byte STA :00EF Save it CALL :E9EE MACC= ABS(MACC) LXI H,:E72B Addr 1/ln2 CALL :EA59 Calc X/ln2 CALL :C21E Result (n+d+z) on stack CALL :E414 Convert MACC to INT (n) CALL :E133 n in ABCD CALL :C234 Get (n+d+z) from stack ORA B ORA C * *********** * FPT EXP * *********** * * Test for overflow is modified. Overflow occurs * for e^X when -45 < X < 43.6. * This is checked now before exponent routine is * entered. * JZ :EFC9 Jump if n <= 255 REM * If X too big: REM LDA :00EF Get exp.byte CMA Take complement ORA A Set flags for error STC Init error exit JMP :E6F5 Run error, abort REM * Find d: REM L1E121 PUSH D Save n CALL :E154 MACC = FRAC (MACC) LXI D,:E6FB Addr FPT(1/8) LHLD :00D5 ORA L JZ :EFF9 CPI :7F JC :E6B8 LXI D,:E6FF Addr FPT(3/8) JMP :E6B8 L1E122 RLC RLC LXI D,:E703 Addr FPT(5/8) JNC :E6B8 LXI D,:E707 Addr FPT(7/8) * L1E123 XCHG Addr d in HL PUSH H Save it CALL :EA6D MACC= MACC-d (z) MOV E,A Exp. z in E LDA :00EF Get exp. X RLC Sign into carry PUSH PSW Save sign MOV A,E Get exp. z CC :E9E4 Evt. change sign LXI H,:00E3 CALL :E9DB Copy z into 00E3-E6 CALL :E9DB and in 00E7-EA LXI H,:C462 Addr a0 (FPT(1)) CALL :E9FB Copy a0 into MACC LXI H,:E72F Addr table a1-a5 CALL :E5AA Calc Taylor sum 2^z POP PSW Get exp.byte X SHL 1, REM sign in CY POP D Get addr FPT(n/8) PUSH PSW LXI H,:0010 Init offset for table L1E283 JNC :E6E6 Jump if X was positive DAD H Offset is #0020 for neg.nr. L1E124 DAD D Calc addr in L1E283 CALL :EA59 Calc 2^z * 2^d POP PSW Get CY on sign of X POP H Get n in H MOV A,H JNC :E6F2 Jump if X was positive CMA ) Else: complement n INR A ) L1E125 CALL :C1B7 Add exponents (n+d+z) L1E126 CC :EA4B Evt error handling L1E127 JMP :C14D Popall, ret REM * CONSTANTS FOR 'XEXP': REM L1E279 DATA :7E FPT(1/8) DATA :80 DATA :00 DATA :00 * L1E280 DATA :7F FPT(3/8) DATA :C0 DATA :00 DATA :00 * L1E281 DATA :00 FPT(5/8) DATA :A0 DATA :00 DATA :00 * L1E282 DATA :00 FPT(7/8) DATA :E0 DATA :00 DATA :00 * * L1E283 DATA :01 2^(1/8) DATA :8B DATA :95 DATA :C2 * DATA :01 2^(3/8) DATA :A5 DATA :FE DATA :D7 * DATA :01 2^(5/8) DATA :C5 DATA :67 DATA :2A * DATA :01 2^(7/8) DATA :EA DATA :C0 DATA :C7 * L1E287 DATA :00 2^(-1/8) DATA :EA DATA :C0 DATA :C7 * DATA :00 2^(-3/8) DATA :C5 DATA :67 DATA :2A * DATA :00 2^(-5/8) DATA :A5 DATA :FE DATA :D7 * DATA :00 2^(-7/8) DATA :8B DATA :95 DATA :C2 * * L1E291 DATA :01 1/LN2 DATA :B8 DATA :AA DATA :3B * * L1E292 DATA :00 a1: LN2 DATA :B1 0.69314718057 DATA :72 DATA :18 * DATA :7E a2: ((LN2)^2)/2! DATA :F5 0.24022648580 DATA :FD DATA :EF * DATA :7C a3: ((LN2)^3)/3! DATA :E3 0.055504105406 DATA :58 DATA :46 * DATA :7A a4: ((LN2)^4)/4! DATA :9D 0.0096217389747 DATA :A4 DATA :81 * DATA :77 a5: ((LN2)^5)/5! DATA :AE 0.0013337729375 DATA :D1 DATA :FE * DATA :00 End of table DATA :00 * ******* * LOG * ******* * * MACC = LN (MACC). * * Method: Polynomial approximation. * * Write X = 2^K * F (normalized written), with * 0.5<= F <1. * If F < SQR(2)/2: J=K-1, G=2*F. * If F > SQR(2)/2: J=K, G=F. * Now X = 2^J * G. * * Assume G=(1+v)/(1-v), then: * ln(X) = J*ln(2) + ln((1+v)/(1-v)). * * ln((1+v)/(1-v))=2(v+v^3/3+v^5/5+...+v^9/9). * Only terms up to v^9 are used. The term constants * are adjusted for minimum error. * * Exit: 00E3-E6: Last significant summand. * 00E7-EA: v^2. * 00EB-EE: Entry MACC (X). * MACC: Result. * All registers preserved. * XLN PUSH PSW PUSH B PUSH D PUSH H CALL :EBF1 Check contents MACC JZ :E9D0 Run argument error if REM MACC = 0 ORA A JM :E9D0 Error if nr is negative CALL :C1E9 Sign extend exp (=K) PUSH PSW Save sign extended exp MVI M,:00 Frig exponent LDA :00D6 Get hibyte mantissa CPI :B5 Compare with SQR(2)/2 JNC :E76A if F < SQR(2)/2 REM * If F > SQR(2)/2: REM LXI H,:C466 Addr FPT(2) CALL :EA59 Calc MACC = 2*F (=G) POP PSW Get K DCR A J=K-1 PUSH PSW Save J * FLNA LXI H,:C462 Addr FPT(1) CALL :EA72 MACC = G+1 CALL :C21E save G+1 on stack LXI H,:C466 Addr FPT(2) CALL :EA6D MACC = G-1 LXI H,:0000 DAD SP HL=SP CALL :EA20 MACC = (G-1)/(G+1) (=v) INX SP ) INX SP ) Suppress 4 bytes INX SP ) on stack INX SP ) LXI H,:00E3 CALL :E9DB Copy v into 00E3-E6 PUSH H Pnts to 00E7 CALL :C21E Save v on stack LXI H,:0000 L1E273 DAD SP HL=SP CALL :EA59 MACC = v^2 INX SP ) INX SP ) Suppress 4 bytes INX SP ) on stack INX SP ) POP H HL=00E7 CALL :E9DB Copy v^2 into 00E7-EA POP D Get J in D MOV A,D ) RAL ) SBB A ) Convert J from 1 byte MOV B,A ) into 4 byte into ABCD MOV C,A ) CALL :E126 Copy ABCD into MACC CALL :E3DE MACC = INT(MACC) LXI H,:E7B8 Addr ln(2) CALL :EA59 MACC=MACC*ln(2) (=J*ln(2)) LXI H,:E7BC Addr Taylor sum constants CALL :E5AA Calc Taylor sum (= ln(X)) JMP :C14D Popall, ret REM * CONSTANTS FOR 'XLN': REM L1E298 DATA :00 LN(2) DATA :B1 DATA :72 DATA :18 * L1E299 DATA :02 b1: FPT (2) DATA :80 DATA :00 DATA :00 * DATA :00 b3: about 2/3 DATA :AA 0.666666564181 DATA :AA DATA :A9 * DATA :7F b5: about 2/5 DATA :CC 0.400018840613 DATA :CF DATA :45 * DATA :7F b7: about 2/7 DATA :91 0.2845357266 DATA :AE DATA :AB * DATA :7E b9: about 2/9 DATA :80 0.125 DATA :00 DATA :00 * DATA :00 End of table DATA :00 * * * END